//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __CMALLOC_H
#define __CMALLOC_H

#include <linknode.h>

#ifndef STDMETHODCALLTYPE
#define STDMETHODCALLTYPE __stdcall
#endif

typedef Int64 TIME;

class CMalloc
{
public:
    CMalloc(){}
    virtual ~CMalloc(){}
public:
    virtual PVoid Alloc(size_t Size);

    virtual PVoid Realloc(PVoid pMem, size_t NewSize);

    virtual void  Free(PVoid pMem);

    size_t STDMETHODCALLTYPE GetSize(
            /* [in] */ PVoid pv);
};

class CMSpyMalloc : public CMalloc
{
public:
    CMSpyMalloc();
    ~CMSpyMalloc();
    
public:
    PVoid Alloc(size_t Size);

    PVoid Realloc(PVoid pMem, size_t NewSize);

    void  Free(PVoid pMem);
    
    void PreAlloc(size_t UserSize);

    void PostAlloc(PVoid pMem, size_t UserSize);

    void PreFree(PVoid pMem);

    void DumpSpyList(TIME lasttime);

    void MemoryStatus();
#ifdef _MSVC
    void TrackStack(ULONG index);
#endif
public:
    // These variables are for heap memory statistic
    DoubleLinkNode *m_pMSpyNodeList;

    RTL_CRITICAL_SECTION m_Lock; // Lock

    unsigned int m_allocIdx;
    unsigned int m_nTotalHeapBlocks;
    unsigned int m_nMaxHeapBlocks;

    // Calculating the whole block not including header
    unsigned int m_nTotalHeapSize;
    unsigned int m_nMaxHeapSize;

    //the emulator max heap memory size
    unsigned int m_nheapLimitSize;

    // Recording the user allocating size
    // Because it's easy to debug
    unsigned int m_nMaxHeapBlockSize;
};

class CPreBChkMalloc : public CMalloc
{
public:
    PVoid Alloc(size_t Size);

    PVoid Realloc(PVoid pMem, size_t NewSize);

    void  Free(PVoid pMem);    
};

class CPostBChkMalloc : public CMalloc
{
public:
    PVoid Alloc(size_t Size);

    PVoid Realloc(PVoid pMem, size_t NewSize);

    void  Free(PVoid pMem);
};

class CHyperMalloc : public CMalloc
{
public:
    CHyperMalloc(CMalloc * pMalloc,
                 Int32 minSpySize,
                 Int32 maxSpySize,
                 Int32 valveSpySize); 
    ~CHyperMalloc();

public:    
    PVoid Alloc(size_t Size);

    PVoid Realloc(PVoid pMem, size_t NewSize);

    void  Free(PVoid pMem);

public:
    CMalloc * m_pSpyMalloc;
    Int32  m_minSpySize;
    Int32  m_maxSpySize;
    Int32  m_valveSpySize;
};

#define MALLOC         0
#define SPYMALLOC      1
#define PREBCHKMALLOC  2
#define POSTBCHKMALLOC 3

#endif // __CMALLOC_H
